#ifndef GAME_H_
#define GAME_H_

#include <Windows.h>

#include "CameraListener.h"
#include <string>
#include <vector>
#include <assert.h>
#include "AntTweakBar.h"
#include "BPhysicsEngine.h"
#include "Grid.h"
#include "SkyBox.h"
#include "Ai_Message.h"
#include "Engine.h"
#include "GameState.h"
#include "ResourceManager.h"
class BehaviourI;
class GodRayRenderer;

/* */
class InteractiveState : public GameState
{
public:
    InteractiveState();
    /* Game State */
    virtual void Update(float dt);
    virtual void Draw();
    virtual void Initialise();
    virtual void CleanUp();
    virtual void OnResume(){Reset();}
    virtual Camera* GetCamera(){return &m_camera[m_cameraSelection];}
    virtual ID3DXEffect* GetEffect(){return m_mainEffect;}
    virtual void NotifyKeyPressDirectInput(int which);
    virtual void NotifyKeyPressSDL(int type, int state, int key);
    virtual void HandleMessage(const char* message);
    virtual BPhysicsEngine* GetPhysicsEngine(){return m_PEngine;}
    virtual void DebugDrawSphere(const Vec3& pos, float radius,const Vec3& color, bool fullSize);
    virtual void DebugDrawHemiSphere(const Vec3& pos, float radius, const Vec3& norm, const Vec3& color, bool fullSize);
    /* Called from Lua */
    void LPopulateColorKey(int key, float r, float g, float b);
    void LPostMessage(int which, float time);
    void LOverwriteMessage(const char* newMessage);
    void LSpawnBox(float x, float y, float z);
    void LSetCameraPosition(float x, float y, float z);
    void LSetCameraDirection(float x, float y, float z);
    void LSetSelectedActor();
    void LEnableActor();
    void LDisableActor();
    void LInitialiseSkyBox(int size_x, int size_y, int size_z,
                           float pos_x, float pos_y, float pos_z);
    void LInitialiseSkyDome(float pos_x, float pos_y, float pos_z, int r);
    void LCreateSphereActor(float radius, float x, float y, float z);
    void LCreateWallActor(  float minX, float minY, float minZ,
                            float maxX, float maxY, float maxZ, float thickness);
    void LCreatePlaneActor(float normX,float normY,float normZ, float offset,
                            float scaleX,float scaleY,float scaleZ);
    void LSetSeekKey(int key);
    void LSetFleeKey(int key);
    void LSetPathKey(int key);
    void LLoadBlock(const char* blockName, const char* buildingName, bool ECHOS);

    /* Utility functions */
    BPhysicsActor* GetSelectedActor(){return m_selectedActor;}
    BehaviourI* GetBehaviour(int key);
    BPhysicsActor* GetPlayerVehiclePointer();
    Grid* GetGridPointer();
    void RenderAudioDebugNodes();

    /* State Specific */
    void StartPhysics();
    void ReleasePhysics();
    void InitialiseConsole();
    void InitializePerception();
    void Reset();
    void DrawConsole();
    void ShaderInit();
    void RenderScene(int pass);
    void HandleGameEvents();
    void HandleConsoleInput();
    void HandleMouseEvents();
    void ManageAI();
    void ManageCameras();
    void ManageCarInput();
    void SetCameraBehindCar();
    void SetCameraToTyre();
    void CreateAIGrid();
    void CreateUI();

    void CreateAudioOptionsBar();

    void CreateControlBarUI();
    void CreateOptionsBarUI();
    void SetUpRenderingVariablesUI();
    void SetUpLightingVariablesUI();
    void SetUpGodRayVariablesUI();
    void CreateConsoleUI();
    void SetUpCameras();
    void ManageUI();
    void DebugDrawSphere(float x, float y, float z, float radius,const Vec3& color);
    void LUpdateTextures();

#pragma region Lua Implementation
public:
    static LuaPlus::LuaObject* GetMetaTable(){return Static_MetaTable;}
    static LuaPlus::LuaObject* StaticInitializeLuaMetaTable();
    static LuaPlus::LuaObject* Static_MetaTable;
#pragma endregion

private:
    // Messaging 
    MessageSystem::Message_Dispatcher m_cityDispatcher;
    MessageSystem::Message_Dispatcher m_vehicleDispatcher;
    //Console
    HANDLE m_consoleInputHandle;
    HANDLE m_consoleOutputHandle;
    LPD3DXFONT m_font;
    std::string m_currentString;
    std::vector<std::string> m_displayStrings;
    int m_maxLines;
    int m_currentIndex;
    char m_buf[256];
    char m_modbuf[256];
    bool m_acceptInput;
    //Utility
    BPhysicsActor* m_selectedActor;
    //AI
    typedef std::map<int, BehaviourI*> BehaviourMap;
    BehaviourMap m_behaviourMap;
    int m_AIMode;
    int m_oldMode;
    //Game State
    BPhysicsEngine* m_PEngine;
    ID3DXEffect* m_mainEffect;
    //State Specific
    BPhysicsActor* m_vehicle;
    int m_numActivePolice;
    BPhysicsActor* m_policeCars[3];
    bool m_renderDebugTexture;
    int m_textureSelection;
    bool m_drawDebug;
    int m_debugDrawMode;
    bool m_drawStandard;
    bool m_drawAudioSources;
    bool m_drawAudioGeom;
    bool m_drawEchoNodes;
    int m_cameraSelection;
    CameraListener m_camera[3];
    bool m_cameraChoice[3];
    float m_cameraHeight;
    D3DXVECTOR3 m_cameraLerpTarget;
    int m_rightClickSelection;
	D3DXMATRIXA16	m_worldMatrix;
    LPDIRECT3DVERTEXBUFFER9 m_texturedQuad;
    int m_quadVerts;
    D3DXVECTOR3 m_lightPositionWorldSpace;
    TwBar* m_optionsBar;
    TwBar* m_controlBar;
    TwBar* m_consoleBar;
    TwBar* m_audioOptionsBar;
    TwBar* m_networkingOptionsBar;
    int m_consoleState;
    D3DXMATRIXA16 m_lightViewMatrix;
    D3DXMATRIXA16 m_lightProjMatrix;
    bool m_shadowMapped;
    Grid m_grid;
    bool m_drawGrid;
    bool m_drawPerception;
    DirectXMesh* m_debugSphereMesh;
    DirectXMesh* m_debugHemiSphereMesh;
    float m_audioDebugAlpha;

    //added quickly to project to make it more usable
    std::vector<std::string> m_vecCommands;
    std::vector<std::string> m_commandDescriptions;
    int m_vecChoice;
    int m_addLocation;
    std::string m_currentCommand;
public:
    void AddLuaCommand(const char* command, const char* description);
    void PushCommand();

private:
    //God Rays
    GodRayRenderer* m_GOD;
    float m_rainSpeed;
    DirectXMesh* m_texturedSphere;
    int m_godRayTextureSelection;
    int m_lightSourceSelection;

public:
    void RenderPerceptionDebug();
    void DrawDebug(int pass);
    void RenderUI(Texture texture);
    void ResetGodRays();

    /************************************************************************/
    /* NETWORKING                                                                     */
    /************************************************************************/
    unsigned int m_numClients;
};

#endif // GAME_H_



